<?php
namespace Admin\Common;
use PhalApi\Exception\InternalServerErrorException;

/**
 * PHP OAuth2封装
 * @author dogstar 20201201
 * @link ttps://bshaffer.github.io/oauth2-server-php-docs/cookbook/
 */
class OAuthServer {

    protected $server;

    public function __construct() {
        $this->init();
    }

    protected function init() {
        $di = \PhalApi\DI();
        $dbCfg = $di->config->get("app.servers.db_master");
        if (empty($dbCfg)) {
            throw new InternalServerErrorException('OAuth数据库未连接');
        }

        // Autoloading (composer is preferred, but for this example let's just do this)
        require_once(API_ROOT . '/src/oauth2-server-php/src/OAuth2/Autoloader.php');
        \OAuth2\Autoloader::register();

        $dsn = sprintf('mysql:dbname=%s;host=%s;port=%d',
            $dbCfg['name'],
            isset($dbCfg['host']) ? $dbCfg['host'] : 'localhost',
            isset($dbCfg['port']) ? $dbCfg['port'] : 3306
        );

        $config = array(
            'client_table' => 'oauth_clients',
            'access_token_table' => 'oauth_access_tokens',
            'refresh_token_table' => 'oauth_refresh_tokens',
            'code_table' => 'oauth_authorization_codes',
            'user_table' => 'oauth_users',
            'jwt_table'  => 'oauth_jwt',
            'jti_table'  => 'oauth_jti',
            'scope_table'  => 'oauth_scopes',
            'public_key_table'  => 'oauth_public_keys',
        );
        //$prefix = $di->config->get("{$dbCfgKey}.tables.__default__.prefix");
        //foreach ($config as &$itRef) {
        //    $itRef = $prefix . $itRef;
        //}

        // $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
        $storage = new \OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $dbCfg['user'], 'password' => $dbCfg['password']), $config);
        
        // Pass a storage object or array of storage objects to the OAuth2 server class
        $server = new \OAuth2\Server($storage);
        
        // Add the "Client Credentials" grant type (it is the simplest of the grant types)
        $server->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));
        
        // Add the "Authorization Code" grant type (this is where the oauth magic happens)
        //$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage));

        // create the grant type
        $server->addGrantType(new \OAuth2\GrantType\UserCredentials($storage));

        $this->server = $server;
    }

    public function getServer() {
        return $this->server;
    }
}
